package com.study.example.gameserver.module.attr.service;

import com.google.common.collect.Maps;
import com.sparrow.common.attr.AttrBox;
import com.sparrow.common.attr.domain.Attr;
import com.sparrow.common.attr.domain.AttrModule;
import com.sparrow.common.thread.IdExecutorGroup;
import com.sparrow.example_message.base.resp.RespAttrUpdatePacket;
import com.study.example.gameserver.module.attr.calculator.AttrCalculator;
import com.study.example.gameserver.module.attr.domain.AttrConst;
import com.study.example.gameserver.module.attr.util.AttrHelper;
import com.study.example.gameserver.module.player.entity.Player;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component
public class AttrService implements BeanPostProcessor {
    private static Logger logger = LoggerFactory.getLogger(AttrService.class);

    private final Map<Class<?>, AttrCalculator> attrCalculatorMap = Maps.newHashMap();

    private AttrModule rootNode;

    @Autowired
    IdExecutorGroup idExecutorGroup;


    @PostConstruct
    public void init() {
        //构造属性结构
        //根节点
        rootNode = AttrConst.rootNode;
        //等级属性节点
        rootNode.addChild(AttrConst.levelNode);
        //装备属性
        rootNode.addChild(AttrConst.equipNode);
    }

    public AttrModule getRootNode() {
        return rootNode;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof AttrCalculator) {
            attrCalculatorMap.put((Class<?>) bean.getClass(), (AttrCalculator) bean);
        }
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }

    public AttrBox createPlayerAttrBox(Player player) {
        AttrBox attrBox = new AttrBox(rootNode);
        attrBox.addAttrChangeListener((road, diff) -> {
            player.getMergeUpdateBox().getMergeUpdateScheduler("MergeCalcFightForce").tryMergeSchedule(idExecutorGroup, player.getPlayerId(),"MergeCalcFightForce", () -> {
                calcFightForce(player);

                sendAttrUpdate(player);
            }, 500, TimeUnit.MILLISECONDS);
        });
        return attrBox;
    }

    public void sendAttrUpdate(Player player) {
        RespAttrUpdatePacket packet = new RespAttrUpdatePacket();
        packet.setFight(player.getFight());
        Attr finalAttr = player.getAttrBox().getFinalAttr();
        Map<Integer, Long> attrMap = finalAttr.toMap();
        packet.setAttrMap(attrMap);
        player.sendPacket(packet);
    }

    public void calcFightForce(Player player) {
        long fightForce = AttrHelper.calcFightForce(player);
        player.getEntity().setFightForce(fightForce);
        player.getEntity().update();
    }

    /**
     * 计算属性
     * @param player
     */
    public void calcAttr(Player player) {
        for (AttrCalculator m : attrCalculatorMap.values()) {
            m.calcAttr(player);
        }
    }

    public AttrCalculator getAttrCalculator(Class<?> clazz) {
        return attrCalculatorMap.get(clazz);
    }



}
